/**
 *  Copyright 2002-2009 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package foo.bar.wiki.services;

import foo.bar.wiki.domain.*;
import foo.bar.wiki.security.RoleType;
import foo.bar.wiki.services.SetupType;
import foo.bar.wiki.security.UserAccountRealm;
import foo.bar.wiki.security.UserAccount;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.meta.MappingTool;
import org.apache.openjpa.lib.util.Options;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.JpaTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;

/**
 * Service that performs one-time, first-time startup initialization procedure upon successfull
 * initialization of Spring's application context.
 * <p/>
 * Initialization procedure includes :-
 * <ul>
 *  <li>Setup the table structure</li>
 *  <li>Setup of data</li>
 * </ul>
 *
 * @author tmjee
 * @version $Date$ $Id$
 */
public class SetupService extends AbstractJpaAwareService implements ApplicationListener, ApplicationContextAware {

    private static final Log LOG = LogFactory.getLog(SetupService.class);

    /** To indicate if Setup is done. */
    public static volatile boolean ready = false;


    private TransactionTemplate transactionTemplate;

    private String dbUsername;
    private String dbPassword;
    private String dbUrl;
    private String dbDriverName;
    private boolean addSampleData = true;
    private boolean doTableSetup = true;

    private ApplicationContext applicationContext;


    public SetupService(){}
    public SetupService(JpaTemplate template, TransactionTemplate transactionTemplate) {
        super(template);
        this.transactionTemplate = transactionTemplate;
    }

    public void setDoTableSetup(boolean doTableSetup) { this.doTableSetup = doTableSetup; }
    public void setAddSampleData(boolean addSampleData) { this.addSampleData = addSampleData; }
    public void setUsername(String dbUsername) { this.dbUsername = dbUsername; }
    public void setPassword(String dbPassword) { this.dbPassword = dbPassword; }
    public void setUrl(String dbUrl) { this.dbUrl = dbUrl; }
    public void setDriverClassName(String dbDriverName) { this.dbDriverName = dbDriverName; }

    protected String getUrl() { return dbUrl; }
    protected String getPassword() { return dbPassword; }
    protected String getDriverClassName() { return dbDriverName; }
    protected String getUsername() { return dbUsername; }


    public void onApplicationEvent(ApplicationEvent event) {
        try {
            if (event instanceof ContextRefreshedEvent) {
                ready = false;
                onStartup((ContextRefreshedEvent)event);
                ready = true;
            }
            if (event instanceof ContextClosedEvent) {
                onShutdown((ContextClosedEvent)event);
                ready = false;
            }
        }
        catch(Throwable e) {
            throw new RuntimeException(e.toString(), e);
        }
    }


    protected void onStartup(ContextRefreshedEvent e) throws Throwable {

        // utilities setup
        ServicesUtil.setApplicationContext(applicationContext);

        // table & data setup
        boolean isSetupBefore = isSetupBefore();
        if (!isSetupBefore) {
            if (doTableSetup) {
                doTableSetup(e);
            }
            if (addSampleData) {
                doDataSetup(e);
            }
            doneSetup();
        }

        // static data setup
        UserAccountRealm.ANONYMOUS_USER_ACCOUNT = new UserAccount(AnonymousUser.INSTANCE, UserAccountRealm.class.getName()+ "_0");
    }

    protected void onShutdown(ContextClosedEvent e) {
    }

    public boolean isSetupBefore() {
        Boolean x =  (Boolean) transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(final TransactionStatus transactionStatus) {
                return getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        try {
                        Query query = entityManager.createNamedQuery("Setup_findByName");
                        query.setParameter("name", SetupType.SETUP_COMPLETED);
                        Setup setup = (Setup) getFirstResult(query);
                        if (setup != null) {
                            return "true".equals(setup.getValue()==null?"":setup.getValue().trim());
                        }
                            return Boolean.FALSE;
                        }
                        catch(Throwable e) {
                            transactionStatus.setRollbackOnly();
                            return Boolean.FALSE;
                        }
                    }
                });
            }
        });
        return x;
    }



    public void doTableSetup(ContextRefreshedEvent e) throws IOException, SQLException {
        // db tables setup
        JDBCConfiguration jdbcConfiguration = new JDBCConfigurationImpl();
        jdbcConfiguration.setConnectionURL(dbUrl);
        jdbcConfiguration.setConnectionUserName(dbUsername);
        jdbcConfiguration.setConnectionDriverName(dbDriverName);
        jdbcConfiguration.setConnectionPassword(dbPassword);
        Options opts = new Options();
        String[] args = opts.setFromCmdLine(new String[] {
            "-p", "META-INF/persistence.xml",
            "-sa", "add",      // or drop  , refresh
            "-dt", "true",
            "-pk", "true",
            "-fk", "true",
            "-ix", "true",
            "-i", "false"

        });
        MappingTool.run(jdbcConfiguration, args, opts);
    }

    


    private User admin = null;
    private User jim = null;
    private User jack = null;
    private User tom = null;
    private User dick = null;


    private Space space1 = null;
    private Space space2 = null;
    private Space space3 = null;
    private Space space4 = null;
    private Space space5 = null;
    private Space space6 = null;
    private Space space7 = null;
    private Space space8 = null;
    private Space space9 = null;
    private Space space10 = null;
    private Space space11 = null;
    private Space space12 = null;

    private Page space1_page1 = null;
    private Page space1_page2 = null;
    private Page space1_page3 = null;
    private Page space1_page4 = null;
    private Page space1_page5 = null;
    private Page space1_page6 = null;
    private Page space1_page7 = null;
    private Page space1_page8 = null;
    private Page space1_page9 = null;
    private Page space1_page10 = null;
    private Page space1_page11 = null;
    private Page space1_page12 = null;
    private Page space1_page13 = null;
    private Page space1_page14 = null;
    private Page space1_page15 = null;
    private Page space1_page16 = null;
    private Page space1_page17 = null;
    private Page space1_page18 = null;
    private Page space1_page19 = null;
    private Page space1_page20 = null;
    private Page space1_page21 = null;
    private Page space1_page22 = null;
    private Page space1_page23 = null;
    private Page space1_page24 = null;
    private Page space1_page25 = null;
    private Page space1_page26 = null;

    private Page space2_page1 = new Page();
    private Page space2_page2 = new Page();
    private Page space2_page3 = new Page();
    private Page space2_page4 = new Page();
    private Page space2_page5 = new Page();
    private Page space2_page6 = new Page();


    protected void doDataSetup_users() throws Throwable {
        transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus transactionStatus) {
                getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        admin = new User();
                        jim = new User();
                        jack = new User();
                        tom = new User();
                        dick = new User();

                        // administrator
                        admin.setUsername("admin");
                        admin.setDisabled(false);
                        admin.setExpiryDate(null);
                        admin.setLocked(false);
                        admin.setEmail("admin@email.com");
                        admin.setPassword("admin");
                        admin.setPermissions(new ArrayList<Permission>());
                        admin.setProperties(new ArrayList<Property>());
                        admin.setRoles(new ArrayList<Role>() {
                            {
                                Role adminRole = new Role();
                                adminRole.setType(RoleType.ADMINISTRATOR);
                                adminRole.setOwner(admin);
                                add(adminRole);
                            }
                        });
                        saveOrUpdate(entityManager, admin);
                        // jim
                        //      - owner/creator of personalBlog
                        jim.setUsername("jim");
                        jim.setDisabled(false);
                        jim.setExpiryDate(null);
                        jim.setLocked(false);
                        jim.setEmail("jim@email.com");
                        jim.setPassword("jim");
                        jim.setPermissions(new ArrayList<Permission>());
                        jim.setProperties(new ArrayList<Property>());
                        jim.setRoles(new ArrayList<Role>() {
                            {
                                Role regUserRole = new Role();
                                regUserRole.setType(RoleType.REGISTERED_USER);
                                regUserRole.setOwner(jim);
                                add(regUserRole);
                            }
                        });
                        saveOrUpdate(entityManager, jim);

                        // jack
                        //      - member of personalBlog
                        jack.setUsername("jack");
                        jack.setDisabled(false);
                        jack.setExpiryDate(null);
                        jack.setLocked(false);
                        jack.setEmail("jack@email.com");
                        jack.setPassword("jack");
                        jack.setPermissions(new ArrayList<Permission>());
                        jack.setProperties(new ArrayList<Property>());
                        jack.setRoles(new ArrayList<Role>() {
                            {
                                Role regUserRole = new Role();
                                regUserRole.setType(RoleType.REGISTERED_USER);
                                regUserRole.setOwner(jack);
                                add(regUserRole);
                            }
                        });
                        saveOrUpdate(entityManager, jack);

                        // tom
                        //      - moderator of personalBlog
                        tom.setUsername("tom");
                        tom.setDisabled(false);
                        tom.setExpiryDate(null);
                        tom.setLocked(false);
                        tom.setEmail("tom@email.com");
                        tom.setPassword("tom");
                        tom.setPermissions(new ArrayList<Permission>());
                        tom.setProperties(new ArrayList<Property>());
                        tom.setRoles(new ArrayList<Role>() {
                            {
                                Role moderatorUserRole = new Role();
                                moderatorUserRole.setType(RoleType.MODERATOR);
                                moderatorUserRole.setOwner(tom);
                                add(moderatorUserRole);
                            }
                        });
                        saveOrUpdate(entityManager, tom);

                        // dick
                        //      - just a registered user, not associated with personalBlog
                        dick.setUsername("dick");
                        dick.setDisabled(false);
                        dick.setExpiryDate(null);
                        dick.setLocked(false);
                        dick.setEmail("dick@email.com");
                        dick.setPassword("dick");
                        dick.setPermissions(new ArrayList<Permission>());
                        dick.setProperties(new ArrayList<Property>());
                        dick.setRoles(new ArrayList<Role>() {
                            {
                                Role moderatorUserRole = new Role();
                                moderatorUserRole.setType(RoleType.REGISTERED_USER);
                                moderatorUserRole.setOwner(dick);
                                add(moderatorUserRole);
                            }
                        });
                        saveOrUpdate(entityManager, dick);

                        return null;
                    }
                });
                return null;
            }
        });
    }

    protected void doDataSetup_users_fav_pages() throws Throwable {
        transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus transactionStatus) {
                getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        admin = entityManager.find(User.class, admin.getId());
                        admin.setFavouritePages(new ArrayList<Page>() {
                            {
                                add(space1_page1);
                                add(space1_page2);
                                add(space1_page3);
                                add(space1_page4);
                                add(space1_page5);
                            }
                        });
                        saveOrUpdate(entityManager, admin);

                        jim = entityManager.find(User.class, jim.getId());
                        jim.setFavouritePages(new ArrayList<Page>() {
                            {
                                add(space1_page6);
                                add(space1_page7);
                                add(space1_page8);
                                add(space1_page9);
                                add(space1_page10);
                            }
                        });
                        saveOrUpdate(entityManager, jim);

                        tom = entityManager.find(User.class, tom.getId());
                        tom.setFavouritePages(new ArrayList<Page>() {
                            {
                                add(space1_page11);
                                add(space1_page12);
                                add(space1_page13);
                                add(space1_page14);
                                add(space1_page15);
                            }
                        });
                        saveOrUpdate(entityManager, tom);

                        jack = entityManager.find(User.class, jack.getId());
                        jack.getFavouritePages().add(space1_page16);
                        jack.getFavouritePages().add(space1_page17);
                        jack.getFavouritePages().add(space1_page18);
                        jack.getFavouritePages().add(space1_page19);
                        jack.getFavouritePages().add(space1_page20);
                        saveOrUpdate(entityManager, jack);

                        dick = entityManager.find(User.class, dick.getId());
                        dick.getFavouritePages().add(space1_page21);
                        dick.getFavouritePages().add(space1_page22);
                        dick.getFavouritePages().add(space1_page23);
                        dick.getFavouritePages().add(space1_page24);
                        dick.getFavouritePages().add(space1_page25);
                        saveOrUpdate(entityManager, dick);

                        return null;
                    }
                });
                return null;
            }
        });
    }

    protected void doDataSetup_spaces() throws Throwable {
        space1 = new Space();
        space1.setName("Space1");
        space1.setDescription("Space 1");
        space1.setCreator(admin);
        space1.setCreationDate(new Date());

        space2 = new Space();
        space2.setName("Space2");
        space2.setDescription("Space 2");
        space2.setCreator(admin);
        space2.setCreationDate(new Date());

        space3 = new Space();
        space3.setName("Space3");
        space3.setDescription("Space 3");
        space3.setCreator(admin);
        space3.setCreationDate(new Date());

        space4 = new Space();
        space4.setName("Space4");
        space4.setDescription("Space 4");
        space4.setCreator(admin);
        space4.setCreationDate(new Date());

        space5 = new Space();
        space5.setName("Space5");
        space5.setDescription("Space 5");
        space5.setCreator(admin);
        space5.setCreationDate(new Date());

        space6 = new Space();
        space6.setName("Space6");
        space6.setDescription("Space 6");
        space6.setCreator(admin);
        space6.setCreationDate(new Date());

        space7 = new Space();
        space7.setName("Space7");
        space7.setDescription("Space 7");
        space7.setCreator(admin);
        space7.setCreationDate(new Date());

        space8 = new Space();
        space8.setName("Space8");
        space8.setDescription("Space 8");
        space8.setCreator(admin);
        space8.setCreationDate(new Date());

        space9 = new Space();
        space9.setName("Space9");
        space9.setDescription("Space 9");
        space9.setCreator(admin);
        space9.setCreationDate(new Date());

        space10 = new Space();
        space10.setName("Space10");
        space10.setDescription("Space 10");
        space10.setCreator(admin);
        space10.setCreationDate(new Date());

        space11 = new Space();
        space11.setName("Space11");
        space11.setDescription("Space 11");
        space11.setCreator(admin);
        space11.setCreationDate(new Date());

        space12 = new Space();
        space12.setName("Space12");
        space12.setDescription("Space 12");
        space12.setCreator(admin);
        space12.setCreationDate(new Date());
        

        transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus transactionStatus) {
                getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        saveOrUpdate(entityManager, space1);
                        saveOrUpdate(entityManager, space2);
                        saveOrUpdate(entityManager, space3);
                        saveOrUpdate(entityManager, space4);
                        saveOrUpdate(entityManager, space5);
                        saveOrUpdate(entityManager, space6);
                        saveOrUpdate(entityManager, space7);
                        saveOrUpdate(entityManager, space8);
                        saveOrUpdate(entityManager, space9);
                        saveOrUpdate(entityManager, space10);
                        saveOrUpdate(entityManager, space11);
                        saveOrUpdate(entityManager, space12);
                        return null;
                        
                    }
                });
                return null;
            }
        });
    }

    protected void doDataSetup_pages() throws Throwable {
        space1_page1 = new Page();
        space1_page2 = new Page();
        space1_page3 = new Page();
        space1_page4 = new Page();
        space1_page5 = new Page();
        space1_page6 = new Page();
        space1_page7 = new Page();
        space1_page8 = new Page();
        space1_page9 = new Page();
        space1_page10 = new Page();
        space1_page11 = new Page();
        space1_page12 = new Page();
        space1_page13 = new Page();
        space1_page14 = new Page();
        space1_page15 = new Page();
        space1_page16 = new Page();
        space1_page17 = new Page();
        space1_page18 = new Page();
        space1_page19 = new Page();
        space1_page20 = new Page();
        space1_page21 = new Page();
        space1_page22 = new Page();
        space1_page23 = new Page();
        space1_page24 = new Page();
        space1_page25 = new Page();
        space1_page26 = new Page();


        space1_page1.setName("space1_page1");
        space1_page1.setDescription("Space 1 Page 1");
        space1_page1.setSpace(space1);
        space1_page1.setContent(" **Space 1 Page 1** ");
        space1_page1.setCreator(admin);
        space1_page1.setCreationDate(new Date());

        space1_page2.setName("space1_page2");
        space1_page2.setDescription("Space 1 Page 2");
        space1_page2.setSpace(space1);
        space1_page2.setContent(" **Space 1 Page 2**");
        space1_page2.setCreator(admin);
        space1_page2.setCreationDate(new Date());

        space1_page3.setName("space1_page3");
        space1_page3.setDescription("Space 1 Page 3");
        space1_page3.setSpace(space1);
        space1_page3.setContent(" **Space 1 Page 3** ");
        space1_page3.setCreator(admin);
        space1_page3.setCreationDate(new Date());

        space1_page4.setName("space1_page4");
        space1_page4.setDescription("Space 1 page 4");
        space1_page4.setSpace(space1);
        space1_page4.setContent(" **Space 1 Page 4** ");
        space1_page4.setCreator(admin);
        space1_page4.setCreationDate(new Date());

        space1_page5.setName("space1_page5");
        space1_page5.setDescription("Space 1 Page 5");
        space1_page5.setSpace(space1);
        space1_page5.setContent(" **Space 1 Page 5** ");

        space1_page6.setName("space1_page6");
        space1_page6.setDescription("Space 1 Page 6");
        space1_page6.setSpace(space1);
        space1_page6.setContent(" **Space 1 Page 6** ");
        space1_page6.setCreator(admin);
        space1_page6.setCreationDate(new Date());

        space1_page7.setName("space1_page7");
        space1_page7.setDescription("Space 1 Page 7");
        space1_page7.setSpace(space1);
        space1_page7.setContent(" **Space 1 Page 7** ");
        space1_page7.setCreator(admin);
        space1_page7.setCreationDate(new Date());

        space1_page8.setName("space1_page8");
        space1_page8.setDescription("Space 1 Page 8");
        space1_page8.setSpace(space1);
        space1_page8.setContent(" **Space 1 Page 8**");
        space1_page8.setCreator(admin);
        space1_page8.setCreationDate(new Date());

        space1_page9.setName("space1_page9");
        space1_page9.setDescription("Space 1 Page 9");
        space1_page9.setSpace(space1);
        space1_page9.setContent(" **Space 1 Page 9** ");
        space1_page9.setCreator(admin);
        space1_page9.setCreationDate(new Date());

        space1_page10.setName("space1_page10");
        space1_page10.setDescription("Space 1 Page 10");
        space1_page10.setSpace(space1);
        space1_page10.setContent(" **Space 1 Page 10** ");
        space1_page10.setCreator(admin);
        space1_page10.setCreationDate(new Date());

        space1_page11.setName("space1_page11");
        space1_page11.setDescription("Space 1 Page 11");
        space1_page11.setSpace(space1);
        space1_page11.setContent(" **Space 1 Page 11** ");
        space1_page11.setCreator(admin);
        space1_page11.setCreationDate(new Date());

        space1_page12.setName("space1_page12");
        space1_page12.setDescription("Space 1 Page 12");
        space1_page12.setSpace(space1);
        space1_page12.setContent(" **Space 1 Page 12** ");
        space1_page12.setCreator(admin);
        space1_page12.setCreationDate(new Date());

        space1_page13.setName("space1_page13");
        space1_page13.setDescription("Space 1 Page 13");
        space1_page13.setSpace(space1);
        space1_page13.setContent(" **Space 1 Page 13** ");
        space1_page13.setCreator(admin);
        space1_page13.setCreationDate(new Date());

        space1_page14.setName("space1_page14");
        space1_page14.setDescription("Space 1 Page 14");
        space1_page14.setSpace(space1);
        space1_page14.setContent(" **Space 1 Page 14** ");
        space1_page14.setCreator(admin);
        space1_page14.setCreationDate(new Date());

        space1_page15.setName("space1_page15");
        space1_page15.setDescription("Space 1 Page 15");
        space1_page15.setSpace(space1);
        space1_page15.setContent(" **Space 1 Page 15** ");
        space1_page15.setCreator(admin);
        space1_page15.setCreationDate(new Date());

        space1_page16.setName("space1_page16");
        space1_page16.setDescription("Space 1 Page 16");
        space1_page16.setSpace(space1);
        space1_page16.setContent(" **Space 1 Page 16** ");
        space1_page16.setCreator(admin);
        space1_page16.setCreationDate(new Date());

        space1_page17.setName("space1_page17");
        space1_page17.setDescription("Space 1 Page 17");
        space1_page17.setSpace(space1);
        space1_page17.setContent(" **Space 1 Page 17** ");
        space1_page17.setCreator(admin);
        space1_page17.setCreationDate(new Date());

        space1_page18.setName("space1_page18");
        space1_page18.setDescription("Space 1 Page 18");
        space1_page18.setSpace(space1);
        space1_page18.setContent(" **Space 1 Page 18** ");
        space1_page18.setCreator(admin);
        space1_page18.setCreationDate(new Date());

        space1_page19.setName("space1_page19");
        space1_page19.setDescription("Space 1 Page 19");
        space1_page19.setSpace(space1);
        space1_page19.setContent(" **Space 1 Page 19** ");
        space1_page19.setCreator(admin);
        space1_page19.setCreationDate(new Date());

        space1_page20.setName("space1_page20");
        space1_page20.setDescription("Space 1 Page 20");
        space1_page20.setSpace(space1);
        space1_page20.setContent(" **Space 1 Page 20** ");
        space1_page20.setCreator(admin);
        space1_page20.setCreationDate(new Date());

        space1_page21.setName("space1_page21");
        space1_page21.setDescription("Space 1 Page 21");
        space1_page21.setSpace(space1);
        space1_page21.setContent(" **Space 1 Page 21** ");
        space1_page21.setCreator(admin);
        space1_page21.setCreationDate(new Date());

        space1_page22.setName("space1_page22");
        space1_page22.setDescription("Space 1 Page 22");
        space1_page22.setSpace(space1);
        space1_page22.setContent(" **Space 1 Page 22** ");
        space1_page22.setCreator(admin);
        space1_page22.setCreationDate(new Date());

        space1_page23.setName("space1_page23");
        space1_page23.setDescription("Space 1 Page 23");
        space1_page23.setSpace(space1);
        space1_page23.setContent(" **Space 1 Page 23** ");
        space1_page23.setCreator(admin);
        space1_page23.setCreationDate(new Date());

        space1_page24.setName("space1_page24");
        space1_page24.setDescription("Space 1 Page 24");
        space1_page24.setSpace(space1);
        space1_page24.setContent(" **Space 1 Page 24** ");
        space1_page24.setCreator(admin);
        space1_page24.setCreationDate(new Date());

        space1_page25.setName("space1_page25");
        space1_page25.setDescription("Space 1 Page 25");
        space1_page25.setSpace(space1);
        space1_page25.setContent(" **Space 1 Page 25** ");
        space1_page25.setCreator(admin);
        space1_page25.setCreationDate(new Date());

        space1_page26.setName("space1_page26");
        space1_page26.setDescription("Space 1 Page 26");
        space1_page26.setSpace(space1);
        space1_page26.setContent(" **Space 1 Page 26** ");
        space1_page26.setCreator(admin);
        space1_page26.setCreationDate(new Date());


        space2_page1 = new Page();
        space2_page2 = new Page();
        space2_page3 = new Page();
        space2_page4 = new Page();
        space2_page5 = new Page();
        space2_page6 = new Page();

        space2_page1.setName("space2_page1");
        space2_page1.setDescription("Space 2 Page 1");
        space2_page1.setSpace(space2);
        space2_page1.setContent(" **Space 2 Page 1** ");
        space2_page1.setCreator(admin);
        space2_page1.setCreationDate(new Date());

        space2_page2.setName("space2_page2");
        space2_page2.setDescription("Space 2 Page 2");
        space2_page2.setSpace(space2);
        space2_page2.setContent(" **Space 2 Page 2** ");
        space2_page2.setCreator(admin);
        space2_page2.setCreationDate(new Date());

        space2_page3.setName("space2_page3");
        space2_page3.setDescription("Space 2 Page 3");
        space2_page3.setSpace(space2);
        space2_page3.setContent(" **Space 2 Page 3** ");
        space2_page3.setCreator(admin);
        space2_page3.setCreationDate(new Date());

        space2_page4.setName("space2_page4");
        space2_page4.setDescription("Space 2 Page 4");
        space2_page4.setSpace(space2);
        space2_page4.setContent(" **Space 2 Page 4** ");
        space2_page4.setCreator(admin);
        space2_page4.setCreationDate(new Date());

        space2_page5.setName("space2_page5");
        space2_page5.setDescription("Space 2 Page 5");
        space2_page5.setSpace(space2);
        space2_page5.setContent(" **Space 2 Page 5** ");
        space2_page5.setCreator(admin);
        space2_page5.setCreationDate(new Date());

        space2_page6.setName("space2_page6");
        space2_page6.setDescription("Space 2 Page 6");
        space2_page6.setSpace(space2);
        space2_page6.setContent(" **Space 2 Page 6** ");
        space2_page6.setCreator(admin);
        space2_page6.setCreationDate(new Date());


        transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus transactionStatus) {
                getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        saveOrUpdate(entityManager, space1_page1);
                        saveOrUpdate(entityManager, space1_page2);
                        saveOrUpdate(entityManager, space1_page3);
                        saveOrUpdate(entityManager, space1_page4);
                        saveOrUpdate(entityManager, space1_page5);
                        saveOrUpdate(entityManager, space1_page6);
                        saveOrUpdate(entityManager, space1_page7);
                        saveOrUpdate(entityManager, space1_page8);
                        saveOrUpdate(entityManager, space1_page9);
                        saveOrUpdate(entityManager, space1_page10);
                        saveOrUpdate(entityManager, space1_page11);
                        saveOrUpdate(entityManager, space1_page12);
                        saveOrUpdate(entityManager, space1_page13);
                        saveOrUpdate(entityManager, space1_page14);
                        saveOrUpdate(entityManager, space1_page15);
                        saveOrUpdate(entityManager, space1_page16);
                        saveOrUpdate(entityManager, space1_page17);
                        saveOrUpdate(entityManager, space1_page18);
                        saveOrUpdate(entityManager, space1_page19);
                        saveOrUpdate(entityManager, space1_page20);
                        saveOrUpdate(entityManager, space1_page21);
                        saveOrUpdate(entityManager, space1_page22);
                        saveOrUpdate(entityManager, space1_page23);
                        saveOrUpdate(entityManager, space1_page24);
                        saveOrUpdate(entityManager, space1_page25);
                        saveOrUpdate(entityManager, space1_page26);

                        saveOrUpdate(entityManager, space2_page1);
                        saveOrUpdate(entityManager, space2_page2);
                        saveOrUpdate(entityManager, space2_page3);
                        saveOrUpdate(entityManager, space2_page4);
                        saveOrUpdate(entityManager, space2_page5);
                        saveOrUpdate(entityManager, space2_page6);
                        return null;
                    }
                });
                return null;
            }
        });
    }

    protected void doDataSetup_pages_creator() throws Throwable {
        transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus transactionStatus) {
                getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        Query q = entityManager.createQuery("SELECT page FROM Page AS page ");
                        for (Iterator i = q.getResultList().iterator(); i.hasNext(); ) {
                           Page page = (Page) i.next();
                           page.setCreator(admin);
                            entityManager.merge(admin);

                        }
                        return null;
                    }
                });
                return null;
            }
        });
    }

    protected void doDataSetup_spaces_creator() throws Throwable {
        transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus transactionStatus) {
                getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        Query q = entityManager.createQuery("SELECT space FROM Space AS space ");
                        for (Iterator i = q.getResultList().iterator(); i.hasNext(); ) {
                           Space space = (Space) i.next();
                           space.setCreator(admin);
                            entityManager.merge(space);
                        }
                        return null;
                    }
                });
                return null;
            }
        });
    }

    protected void doDataSetup_cleanup() throws Throwable {
        admin = null;
        jim = null;
        jack = null;
        tom = null;
        dick = null;

        space1 = null;
        space2 = null;

        space1_page1 = null;
        space1_page2 = null;
        space1_page3 = null;
        space1_page4 = null;
        space1_page5 = null;
        space1_page6 = null;
        space1_page7 = null;
        space1_page8 = null;
        space1_page9 = null;
        space1_page10 = null;
        space1_page11 = null;
        space1_page12 = null;
        space1_page13 = null;
        space1_page14 = null;
        space1_page15 = null;
        space1_page16 = null;
        space1_page17 = null;
        space1_page18 = null;
        space1_page19 = null;
        space1_page20 = null;
        space1_page21 = null;
        space1_page22 = null;
        space1_page23 = null;
        space1_page24 = null;
        space1_page25 = null;
        space1_page26 = null;

        space2_page1 = null;
        space2_page2 = null;
        space2_page3 = null;
        space2_page4 = null;
        space2_page5 = null;
        space2_page6 = null;
    }

    public void doDataSetup(ContextRefreshedEvent e) throws Throwable {
        doDataSetup_users();
        doDataSetup_spaces();
        doDataSetup_pages();
        doDataSetup_users_fav_pages();
        doDataSetup_spaces_creator();
        doDataSetup_pages_creator();
        doDataSetup_cleanup();
    }

    public void doneSetup() throws Throwable {
        transactionTemplate.execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus transactionStatus) {
                getJpaTemplate().execute(new JpaCallback(){
                    public Object doInJpa(EntityManager entityManager) throws PersistenceException {
                        Query query = entityManager.createNamedQuery("Setup_findByName");
                        query.setParameter("name", SetupType.SETUP_COMPLETED);
                        Setup setup = (Setup) getFirstResult(query);
                        if (setup == null) {
                            setup = new Setup();
                            setup.setName(SetupType.SETUP_COMPLETED);
                            setup.setValue("true");
                        } else {
                            setup.setValue("true");
                        }
                        saveOrUpdate(entityManager, setup);
                        return null;  
                    }
                });
                return null;
            }
        });
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
